#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

class String
{
public:
    String();
    String(const char * );
    String(const String &);
    String & operator=(const String &);
    ~String();


#if 0
    String(String && rhs)
    : _pstr(rhs._pstr) //浅拷贝
    {
        cout << "String(String &&)" << endl;
        rhs._pstr = nullptr;//修改右值中的指向
    }

    //称为移动赋值运算符函数
    String & operator=(String && rhs)
    {   //rhs在函数栈空间中是左值，可以取地址
        cout << "String & operator=(String &&)" << endl;
        if(this != &rhs) {//防止自移动
            delete [] _pstr;
            _pstr = rhs._pstr;//浅拷贝
            rhs._pstr = nullptr;//修改右值的指向
        }
        return *this;
    }
#endif

    void print() const;

    const char * c_str() const {    return _pstr;   }

    size_t length() const { 
        //当传递空指针过来时，strlen会直接崩溃
        if(_pstr) {
            return strlen(_pstr);
        }
        return 0;
    }


    friend std::ostream & operator<<(std::ostream & os, const String & rhs);

private:
    char * _pstr;
};

std::ostream & operator<<(std::ostream & os, const String & rhs)
{
    if(rhs._pstr)
        os << rhs._pstr;
    return os;
}

String::String()
    : _pstr(nullptr)
{   
    cout << "String()" << endl; 
}

String::String(const char * pstr)
    : _pstr(new char[strlen(pstr) + 1]())
{
    cout << "String(const char*)" << endl;
    strcpy(_pstr, pstr);
}

String::String(const String & rhs)
    : _pstr(new char[strlen(rhs._pstr) + 1]())
{
    cout << "String(const String &)" << endl;
    strcpy(_pstr, rhs._pstr);
}

String & String::operator=(const String & rhs)
{
    cout << "operator=(const String&)" << endl;
    if(this != &rhs) {
        delete [] _pstr;
        _pstr = new char[strlen(rhs._pstr) + 1]();
        strcpy(_pstr, rhs._pstr);
    }
    return *this;
}

void String::print() const
{   
    //char* 的nullptr，由cout进行输出时，会导致程序直接崩溃
    //而且还没有报错信息
    if(_pstr) {
        cout << _pstr << endl;  
    }
}

String::~String()
{
    cout << "~String()" << endl;
    delete [] _pstr;
    _pstr = nullptr;
}


String func2()
{
    //在没有定义具有移动语义的函数时，
    //执行return语句时，会看到拷贝构造函数的调用
    String s1("world");
    cout << "s1:" << s1 << endl;
    return s1;
}


void test0()
{
    func2();
}

int main()
{
    test0();
    return 0;
}

